//this file is part of eMule
//Copyright (C)2002-2005 Merkur ( devs@emule-project.net / http://www.emule-project.net )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#include "stdafx.h"
#include <io.h>
#include <share.h>
#include "Preferences.h"
#include "..\pkmp.h"
#include "ini2.h"
#include <skylark2/bkdb.h>


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CPreferences thePrefs;

TCHAR	CPreferences::datetimeformat4log[64];
TCHAR	CPreferences::datetimeformat[64];
CString CPreferences::appdir;
CString CPreferences::configdir;
CString CPreferences::m_strWebServerDir;
CString CPreferences::m_strLangDir;
CString CPreferences::m_strFileCommentsFilePath;
CString	CPreferences::m_strLogDir;
CString CPreferences::m_strDbName;
WORD	CPreferences::m_wWinVer;
bool	CPreferences::log2disk;
bool	CPreferences::debug2disk;
int		CPreferences::iMaxLogBuff;
UINT	CPreferences::uMaxLogFileSize;
WORD	CPreferences::m_wLanguageID;
CString CPreferences::m_strScriptsDir;

CString CPreferences::m_strPluginDir;
CString CPreferences::m_strAttachDir;
CString CPreferences::m_strPluginsConfigFile;

bool	CPreferences::showSplash ;

bool	CPreferences::newView ;

ProxySettings CPreferences::proxy;
MainSettings		 CPreferences::m_MainSettings;
PasswordSettings	 CPreferences::m_PswSettings;
ToolBoxSettings		 CPreferences::m_TbxSettings;

CPreferences::CPreferences()
{
//#ifdef _DEBUG
//	m_iDbgHeap = 1;
//#endif
}

CPreferences::~CPreferences()
{
	
}

LPCTSTR CPreferences::GetConfigFile()
{
	return m_strFileCommentsFilePath;
}

void CPreferences::Init()
{
	//srand((uint32)time(0)); // we need random numbers sometimes

	

	//get application start directory
	TCHAR buffer[490];
	::GetModuleFileName(0, buffer, 490);
	LPTSTR pszFileName = _tcsrchr(buffer, L'\\') + 1;
	*pszFileName = L'\0';
	m_strPluginsConfigFile = m_strPluginDir + _T("PKMP.XML");
	appdir = buffer;
	configdir = appdir + CONFIGFOLDER;
	m_strWebServerDir = appdir + L"webserver\\";
	m_strLangDir = appdir + L"lang\\";
	m_strFileCommentsFilePath = configdir + L"PKMP.ini";
	m_strLogDir = appdir + L"logs\\";
	m_strDbName = appdir + SQLITE3DB;

	///////////////////////////////////////////////////////////////////////////
	// Create 'config' directory (and optionally move files from application directory)
	//
	::CreateDirectory(GetConfigDir(), 0);

	///////////////////////////////////////////////////////////////////////////
	// Create 'logs' directory (and optionally move files from application directory)
	//
	::CreateDirectory(GetLogDir(), 0);
	m_strScriptsDir = appdir + SCRIPTS;
	::CreateDirectory(GetScriptsDir(), 0);
	m_strPluginDir = appdir + PLUGINS;
	::CreateDirectory(GetPluginsDir(), 0);
	
	m_strAttachDir = appdir + ATTACHFOLDER;
	::CreateDirectory(m_strAttachDir,0);
	/*CFileFind ff;
	BOOL bFoundFile = ff.FindFile(GetAppDir() + L"PKMP*.log", 0);
	while (bFoundFile)
	{
		bFoundFile = ff.FindNextFile();
		if (ff.IsDots() || ff.IsSystem() || ff.IsDirectory() || ff.IsHidden())
			continue;
		MoveFile(ff.GetFilePath(), GetLogDir() + ff.GetFileName());
	}*/

	LoadPreferences();
	init_pkmplog(thePrefs.GetAppDir() + L"pkmp.properties");
	
}

void CPreferences::InitDB()
{
	CString strFile = thePrefs.GetDB();
	Skylark::init_dblog(thePrefs.GetAppDir() + L"bkdb.properties");
	CComPtr<Skylark::ISQLiteComDatabase3> m_pDB;
	do
	{
		HMODULE hMod = LoadLibraryW(L"bkdb.dll");
		if(hMod == NULL) break;

		PFN_BKDbCreateObject pBKDbCreateObject = (PFN_BKDbCreateObject)GetProcAddress(hMod, "BKDbCreateObject");
		if(pBKDbCreateObject == NULL) break;

		HRESULT hr = pBKDbCreateObject(__uuidof(Skylark::ISQLiteComDatabase3), (void**)&m_pDB, BKENG_CURRENT_VERSION);
		if(!SUCCEEDED(hr)) break;

		hr = m_pDB->Open(strFile);
		if(!SUCCEEDED(hr)) break;

		m_pDB->SetBusyTimeout(3000);
		m_pDB->ExecuteUpdate(L"PRAGMA page_size=4096;");
		m_pDB->ExecuteUpdate(L"PRAGMA encoding = \"UTF-16\";");
		static LPCWSTR strCrKm_Article = L"CREATE TABLE [KM_Article] ("
					L"[ID] INTEGER  PRIMARY KEY AUTOINCREMENT NOT NULL,"
					L"[ClassID] INTEGER  NOT NULL,"
					L"[Title] NVARCHAR(200)  NOT NULL,"
					L"[Content] TEXT  NULL,"
					L"[Author] NVARCHAR(20)  NULL,"
					L"[Creator] NVARCHAR(20)  NULL,"
					L"[Editor] NVARCHAR(20)  NULL,"
					L"[TimeCreated] DATE DEFAULT CURRENT_DATE NULL,"
					L"[TimeEdit] DATE  NULL,"
					L"[TimeRead] DATE  NULL,"
					L"[Hits] INTEGER  NULL,"
					L"[Level] INTEGER  NULL,"
					L"[BookMark] TEXT  NULL,"
					L"[Type] NVARCHAR(20)  NULL,"
					L"[KeyWords] NVARCHAR(100) NULL,"
					L"[LabID] INTEGER  NULL);";
					
		static LPCWSTR strCrKm_art_tags= L"CREATE TABLE [KM_Article_Tags] ("
					L"[ID] INTEGER  NOT NULL,"
					L"[TagID] INTEGER  NOT NULL,"
					L",PRIMARY KEY ([ID],[TagID]));";

		static LPCWSTR strCrKm_category	=L"CREATE TABLE [KM_Category] ("
					L"[ClassID] INTEGER  PRIMARY KEY AUTOINCREMENT NOT NULL,"
					L"[Parent] INTEGER  NULL,"
					L"[PwMasterId] INTEGER  NULL,"
					L"[Category] NVARCHAR(60)  NOT NULL,"
					L"[ClassType] VARCHAR(12)  NOT NULL,"
					L"[Icon] INTEGER  NOT NULL);";

		static LPCWSTR strCrKm_Dict = L"CREATE TABLE [KM_Dict] ("
					L"[ID] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,"
					L"[Key] NVARCHAR(30)  NOT NULL,"
					L"[ClassID] INTEGER  NOT NULL,"
					L"[Content] TEXT  NOT NULL,"
					L"[Sample] TEXT  NULL);";
					
		static LPCWSTR strCrKm_Label = L"CREATE TABLE [KM_Label] ("
					L"[LabID] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,"
					L"[LabName] NVARCHAR(30)  NULL,"
					L"[Icon] VARCHAR(100)  NULL);";
		static LPCWSTR strCrKm_Tags = L"CREATE TABLE [KM_Tags] ("
					L"[TagID] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,"
					L"[TagName] NVARCHAR(40)  NOT NULL);";
		static LPCWSTR strCrKm_Attach = L"CREATE TABLE [KM_Attach] ("
					L"[ID] INTEGER  NOT NULL,"
					L"[Name] NVARCHAR(200)  NOT NULL,"
					L"[FileSize] INTEGER NOT NULL,"
					L"[FileType] NVARCHAR(20) NOT NULL,"
					L"[FileName] NVARCHAR(256) NOT NULL,"
					L"[FilePath] NVARCHAR(512) NOT NULL,"
					L"[TimeEdit] DATE  NULL);";
		//static LPCWSTR strCrCateIdx = CREATE INDEX [IDX_Category_ClassID] ON [KM_Category](
		//			[ClassID]  ASC
		//			);";
		static LPCWSTR strCrKm_PWMaster = L"CREATE TABLE [KM_PWMaster] ("
					L"[ID] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,"
					L"[Type] NVARCHAR(5)  NOT NULL,"
					L"[MasterName] NVARCHAR(60)  NOT NULL,"
					L"[PswAndKey] INTEGER NOT NULL,"
					L"[KeyFile] NVARCHAR(256)  NULL,"
					L"[MasterSeed] BLOB  NULL,"
					L"[EncryptionIV] BLOB NULL,"
					L"[ContentsHash] BLOB NULL,"
					L"[MasterSeed2] BLOB  NULL,"
					L"[KeyEncRounds] INTEGER NULL);";

		static LPCWSTR strCrKm_Password = L"CREATE TABLE [KM_Password] ("
					L"[ID] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,"
					L"[MasterID] INTEGER  NOT NULL,"
					L"[ClassID] INTEGER  NOT NULL,"
					L"[Title] NVARCHAR(60)  NOT NULL,"
					L"[UserName] BLOB NOT NULL,"
					L"[Password] BLOB NOT NULL,"
					L"[Address] NVARCHAR(256) NULL,"
					L"[Remark] NVARCHAR(256) NULL,"
					L"[TimeCreated] DATE  NOT NULL,"
					L"[TimeEdit] DATE  NOT NULL,"
					L"[TimeAccess] DATE  NOT NULL,"
					L"[TimeExpire] DATE  NULL,"
					L"[AttachName] NVARCHAR  NULL,"
					L"[Icon] INTEGER  NULL,"
					L"[ACLen] INTEGER  NULL,"
					L"[AttachContent] BLOB  NULL);";
		static LPCWSTR strCrKm_ShortCut = L"CREATE TABLE [Km_ShortCut] ("
					L"[ID] INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,"
					L"[ClassID] INTEGER  NOT NULL,"
					L"[Title] NVARCHAR(60)  NOT NULL,"
					L"[Address] NVARCHAR(256) NOT NULL,"
					L"[Type] INTEGER NOT NULL);";

		if(!m_pDB->TableExists(L"KM_Article"))
			m_pDB->ExecuteUpdate(strCrKm_Article);

		if(!m_pDB->TableExists(L"KM_Article_Tags"))
			m_pDB->ExecuteUpdate(strCrKm_art_tags);

		if(!m_pDB->TableExists(L"KM_Category"))
			m_pDB->ExecuteUpdate(strCrKm_category);
		
		if(!m_pDB->TableExists(L"KM_Dict"))
			m_pDB->ExecuteUpdate(strCrKm_Dict);
		
		if(!m_pDB->TableExists(L"KM_Label"))
			m_pDB->ExecuteUpdate(strCrKm_Label);
				
		if(!m_pDB->TableExists(L"KM_Tags"))
			m_pDB->ExecuteUpdate(strCrKm_Tags);
		if(!m_pDB->TableExists(L"KM_Attach"))
			m_pDB->ExecuteUpdate(strCrKm_Attach);

		if(!m_pDB->TableExists(L"KM_PWMaster"))
			m_pDB->ExecuteUpdate(strCrKm_PWMaster);

		if(!m_pDB->TableExists(L"KM_Password"))
			m_pDB->ExecuteUpdate(strCrKm_Password);
		if(!m_pDB->TableExists(L"Km_ShortCut"))
			m_pDB->ExecuteUpdate(strCrKm_ShortCut);
	}
	while(FALSE);
}
void CPreferences::LoadPreferences()
{

	CIni ini(GetConfigFile(), L"PKMP");

	
	ini.SetSection(L"PKMP");

	CString strCurrVersion, strPrefsVersion;

	
	strPrefsVersion = ini.GetString(L"AppVersion");

	

	_stprintf(datetimeformat,L"%s",ini.GetString(L"DateTimeFormat",L"%A, %c"));
	if (_tcslen(datetimeformat)==0) _tcscpy(datetimeformat,L"%A, %c");
	_stprintf(datetimeformat4log,L"%s",ini.GetString(L"DateTimeFormat4Log",L"%c"));
	if (_tcslen(datetimeformat4log)==0) _tcscpy(datetimeformat4log,L"%c");

	

	log2disk = ini.GetBool(L"SaveLogToDisk",false);
	uMaxLogFileSize = ini.GetInt(L"MaxLogFileSize", 1024*1024);
	iMaxLogBuff = ini.GetInt(L"MaxLogBuff",64) * 1024;
	
	showSplash	 = ini.GetBool(L"ShowSplash",true);
	newView		= ini.GetBool(L"NewView",true);
	///////////////////////////////////////////////////////////////////////////
	// Section: "Proxy"
	//
	proxy.EnablePassword = ini.GetBool(L"ProxyEnablePassword",false,L"Proxy");
	proxy.UseProxy = ini.GetBool(L"ProxyEnableProxy",false,L"Proxy");
	proxy.name = CStringA(ini.GetString(L"ProxyName", L"", L"Proxy"));
	proxy.user = CStringA(ini.GetString(L"ProxyUser", L"", L"Proxy"));
	proxy.password = CStringA(ini.GetString(L"ProxyPassword", L"", L"Proxy"));
	proxy.port = (uint16)ini.GetInt(L"ProxyPort",1080,L"Proxy");
	//proxy.type = (uint16)ini.GetInt(L"ProxyType",PROXYTYPE_NOPROXY,L"Proxy");
	//load 
	ini.SetSection(SETTING_SECTION_MAIN);
	m_MainSettings.Auto_Start = ini.GetBool(SETTING_AUTOSTART);
	m_MainSettings.Auto_Upgrade = ini.GetBool(SETTING_UPG_A);
	m_MainSettings.Default_Knowledge = ini.GetBool(SETTING_DF_KNL);
	m_MainSettings.Default_Password = ini.GetBool(SETTING_DF_PSW);
	m_MainSettings.Default_Toolbox = ini.GetBool(SETTING_DF_TBX);
	m_MainSettings.Manual_Upgrade = ini.GetBool(SETTING_UPG_Q);
	m_MainSettings.Use_Proxy = ini.GetBool(SETTING_PROXY);

	ini.SetSection(SETTING_SECTION_PASSWORD);
	m_PswSettings.Clear_Clipboard = ini.GetBool(SETTING_PSW_CLEAR,true);
	m_PswSettings.Idle_Second = ini.GetInt(SETTING_PSW_LOCK_TEXT);
	m_PswSettings.Lock_When_Idle = ini.GetBool(SETTING_PSW_LOCK_IDLE);
	m_PswSettings.Lock_When_Min = ini.GetBool(SETTING_PSW_LOCK_MIN);
	m_PswSettings.Lock_When_Switch = ini.GetBool(SETTING_PSW_LOCK_SWITCH);
	m_PswSettings.Wait_Second = ini.GetInt(SETTING_PSW_CLEAR_S,10);
	m_PswSettings.Psw_Min_Len = ini.GetInt(SETTING_PSW_MIN_LEN);
	m_PswSettings.Psw_Qual_Len = ini.GetInt(SETTING_PSW_QUAL_LEN);
	m_PswSettings.Genp_Profile = ini.GetString(SETTING_PSW_GENPROFILE);

	ini.SetSection(SETTING_SECTION_TOOLBOX);
	m_TbxSettings.Auto_Hide = ini.GetBool(SETTING_TBX_AUTO_HIDE);
	m_TbxSettings.Floating_Trpa = ini.GetBool(SETTING_TBX_FLOAT_TRS);
	m_TbxSettings.FTransparent_Value  = ini.GetInt(SETTING_TBX_FLOAT_TRS_TEXT);
	m_TbxSettings.Min_Transparent = ini.GetBool(SETTING_TBX_TRANSPARENT);
	m_TbxSettings.MTransparent_Value = ini.GetInt(SETTING_TBX_TRANS_TEXT);
	m_TbxSettings.Show_Floating = ini.GetBool(SETTING_TBX_SHOW_FLOATING);
	m_TbxSettings.Show_Max = ini.GetBool(SETTING_TBX_SHOW_MAX);
	m_TbxSettings.Show_Min = ini.GetBool(SETTING_TBX_SHOW_MIN);


}

void CPreferences::Uninit()
{
	
}

void CPreferences::SetStandartValues()
{


	WINDOWPLACEMENT defaultWPM;
	defaultWPM.length = sizeof(WINDOWPLACEMENT);
	defaultWPM.rcNormalPosition.left=10;defaultWPM.rcNormalPosition.top=10;
	defaultWPM.rcNormalPosition.right=700;defaultWPM.rcNormalPosition.bottom=500;
	defaultWPM.showCmd=0;
	


//	Save();
}

// SLUGFILLER: SafeHash
bool CPreferences::IsConfigFile(const CString& rstrDirectory, const CString& rstrName)
{

	// do not share a file from the config directory, if it contains one of the following extensions
	static const LPCTSTR _apszNotSharedExts[] = { L".met.bak", L".ini.old" };
	for (int i = 0; i < ARRSIZE(_apszNotSharedExts); i++){
		int iLen = _tcslen(_apszNotSharedExts[i]);
		if (rstrName.GetLength()>=iLen && rstrName.Right(iLen).CompareNoCase(_apszNotSharedExts[i])==0)
			return true;
	}

	

	return false;
}
bool	CPreferences::Save()
{
	SavePreferences();
	return true;
}
void CPreferences::SavePreferences()
{
	CString buffer;
	
	CIni ini(GetConfigFile(), L"PKMP");
	//---
	//ini.WriteString(L"AppVersion", theApp.m_strCurVersionLong);
	//---



	
	ini.WriteWORD(L"Language",m_wLanguageID);
	
	ini.WriteBool(L"Splashscreen",showSplash);
	ini.WriteBool(L"NewView",newView);
	///////////////////////////////////////////////////////////////////////////
	// Section: "Proxy"
	//
	ini.WriteBool(L"ProxyEnablePassword",proxy.EnablePassword,L"Proxy");
	ini.WriteBool(L"ProxyEnableProxy",proxy.UseProxy,L"Proxy");
	ini.WriteString(L"ProxyName",CStringW(proxy.name),L"Proxy");
	ini.WriteString(L"ProxyPassword",CStringW(proxy.password),L"Proxy");
	ini.WriteString(L"ProxyUser",CStringW(proxy.user),L"Proxy");
	ini.WriteInt(L"ProxyPort",proxy.port,L"Proxy");
	ini.WriteInt(L"ProxyType",proxy.type,L"Proxy");


	ini.SetSection(SETTING_SECTION_MAIN);
	ini.WriteBool(SETTING_AUTOSTART,m_MainSettings.Auto_Start) ;
	ini.WriteBool(SETTING_UPG_A,m_MainSettings.Auto_Upgrade);
	ini.WriteBool(SETTING_DF_KNL,m_MainSettings.Default_Knowledge);
	ini.WriteBool(SETTING_DF_PSW,m_MainSettings.Default_Password );
	ini.WriteBool(SETTING_DF_TBX,m_MainSettings.Default_Toolbox) ;
	ini.WriteBool(SETTING_UPG_Q,m_MainSettings.Manual_Upgrade) ;
	ini.WriteBool(SETTING_PROXY,m_MainSettings.Use_Proxy) ;

	ini.SetSection(SETTING_SECTION_PASSWORD);
	ini.WriteBool(SETTING_PSW_CLEAR,m_PswSettings.Clear_Clipboard) ;
	ini.WriteInt(SETTING_PSW_LOCK_TEXT,m_PswSettings.Idle_Second );
	ini.WriteBool(SETTING_PSW_LOCK_IDLE,m_PswSettings.Lock_When_Idle) ;
	ini.WriteBool(SETTING_PSW_LOCK_MIN,m_PswSettings.Lock_When_Min) ;
	ini.WriteBool(SETTING_PSW_LOCK_SWITCH,m_PswSettings.Lock_When_Switch ) ;
	ini.WriteInt(SETTING_PSW_CLEAR_S,m_PswSettings.Wait_Second) ;
	ini.WriteInt(SETTING_PSW_MIN_LEN,m_PswSettings.Psw_Min_Len) ;
	ini.WriteInt(SETTING_PSW_QUAL_LEN,m_PswSettings.Psw_Qual_Len) ;
	ini.WriteString(SETTING_PSW_GENPROFILE,m_PswSettings.Genp_Profile) ;

	ini.SetSection(SETTING_SECTION_TOOLBOX);
	ini.WriteBool(SETTING_TBX_AUTO_HIDE,m_TbxSettings.Auto_Hide) ;
	ini.WriteBool(SETTING_TBX_FLOAT_TRS,m_TbxSettings.Floating_Trpa) ;
	ini.WriteInt(SETTING_TBX_FLOAT_TRS_TEXT,m_TbxSettings.FTransparent_Value) ;
	ini.WriteBool(SETTING_TBX_TRANSPARENT,m_TbxSettings.Min_Transparent) ;
	ini.WriteInt(SETTING_TBX_TRANS_TEXT,m_TbxSettings.MTransparent_Value) ;
	ini.WriteBool(SETTING_TBX_SHOW_FLOATING,m_TbxSettings.Show_Floating) ;
	ini.WriteBool(SETTING_TBX_SHOW_MAX,m_TbxSettings.Show_Max) ;
	ini.WriteBool(SETTING_TBX_SHOW_MIN,m_TbxSettings.Show_Min) ;

}
// SLUGFILLER: SafeHash
